<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* Business_Controller
* Thực hiện xử lý việc chuyển mạch và gọi sang các business để xử lý nghiệp vụ, sau đó trả kết quả về cho nơi gọi (Controller...)
*/
class Business_Controller
{
	function __construct()
	{
		
	}
    
    const STATUS_OK     = 'OK';
    const STATUS_FAILED    = 'FAILED';
    
    protected $haveReturnedData = false;
    
    private function printoutReturnedData_json($data)
    {
        echo json_encode($data);
    }
    
    private function printoutReturnedData_pre($data)
    {
        echo '<pre>', print_r($data, true), '</pre>';
    }
    
    /**
    * return data to caller client
    * 
    * @param string $status status of response. It should be defined at {@link STATUS_XXX}
    * @param mixed $returnData
    */
    protected function returnWithStatus($status, $returnData)
    {
        $this->haveReturnedData = true;
        
        $data = array(
            'status'=>$status,
            'data'=>$returnData,
        );
        
        /**
        * This part will decide default output's formation. In debug mode, it should be 'pre'. Just change it into 'json' when release
        * 
        * TODO -c release : change default output formation into 'json'
        */
        $outputFormat = isset($_GET['rf']) ? $_GET['rf'] : 'pre';
        #$outputFormat = isset($_GET['rf']) ? $_GET['rf'] : 'json';
        
        $printoutFunc = 'printoutReturnedData_'.$outputFormat;
        
        $this->$printoutFunc($data);
        
        return true;
    }
    
    /**
    * Alias for {@link returnWithStatus} with status = {@link STATUS_OK}
    * 
    * @param mixed $data
    */
    protected function returnOK($data)
    {
        return $this->returnWithStatus(self::STATUS_OK, $data);
    }
    
    /**
    * Alias for {@link returnWithStatus} with status = {@link STATUS_FAILED}
    * 
    * @param mixed $data
    */
    protected function returnFailed($data)
    {
        return $this->returnWithStatus(self::STATUS_FAILED, $data);
    }
    
    /**
    * Thực hiện gọi và xử lý nghiệp vụ ở tầng business
    * 
    * @param ReflectionMethod $method
    */
    function _processBusiness($businessname,$method,$args=array())
    {
    	$businessname.="_b";  
        //Kiểm tra sự tồn tại của business class
        if(!file_exists(BUSINESS_PATH."/".strtolower($businessname.".php"))) {
        		throw new Exception('Business not found', 404);
        }
        
        //Load business class
        require_once BUSINESS_PATH."/".strtolower($businessname.".php");
        $business=new $businessname();
        
        //Kiểm tra khả năng được gọi method
        if (!is_callable(array($business, $method))) 
            throw new Exception('Business method not found', 404);
        
        $method = new ReflectionMethod($business, $method);
        $params = array();
        $paramsValue = array();
        foreach ($method->getParameters() as $p) {
            $name = $p->getName();
            if (isset($args[$name])) {
                $paramsValue[$name] = $args[$name];
                continue;
            }    
            if (!$p->isOptional()) throw new Exception("Argument {$name} is missing. Please take a look into the document");
            $paramsValue = $p->getDefaultValue();     
           
        }                 
        try {
            $data = $method->invokeArgs($business, $paramsValue);
            return array(TRUE,$data);
        } catch (SQLException $e) {
            //TODO: ghi log dev
        } catch (ModelException $e ){
            return array(FALSE,$e->getMessage());
        } catch (BusinessException $e ){
            return array(FALSE,$e->getMessage());
        } catch (Exception $e) {
            return array(FALSE,$e->getMessage());
        }
    }
}
